#ifndef _PLAN_H_
#define _PLAN_H_


#include <iostream>
#include <map>
#include <stdio.h>
#include <utility>
#include <list>
#include <string>
#include "debug.h"
#include "Action.h"
#include "ActionPatrol.h"
#include "ActionEat.h"
#include "ActionAttack.h"
#include "ActionDie.h"
#include "ActionFlee.h"
#include "ActionGetItem.h"
#include "ActionSleep.h"
#include "ActionTurnAround.h"
#include "ActionHunt.h"

class NPCEntity ;
class Action ;

/*! this class provides a simple plan implentation, enabling npcs to chain actions in order to 
get a reward according to their desires */
class Plan
{
	protected :
	std::list<Action *> plan__ ; /**< the plan itself (a stack of actions) */
	std::string name__ ;	/**< plan's name (attack, defend, find allies...) */
	std::list<std::pair<std::string,float> > reward__ ;	/**< reward for achieving the plan */ 
	float timeElapsed__ ; /** Time Since the plan has been started */


	public:
	Plan(); /**< Empty constructor */
	Plan(std::string name);	/**< Constructor by name */
	Plan(const Plan& p);	/**< Copy constructor */
	Plan(std::list<Action *> plan__,std::string name__,std::list<std::pair<std::string,float> > reward__); /*!< constructor with parameters */

	virtual ~Plan(); /*!< destructor */

	/*! return the rewards associated to the plan */
	std::list<std::pair<std::string,float> > getReward();
	/*! adds an extra action on the top of the plan */
	void addAction(Action * a); 
	/*! provides a pointer to the action on the top of the plan */
	Action * getFirstAction();

	/*! removes first action of the plan */
	void removeFirstAction();
	/*! removes the top action (depreciated function) */
	void removeFirstActionFromPlan();
	/*! returns a copy of the current plan */
	std::list<Action*> getPlan() ;

	/*! sets a new name for the plan */
	void setName(std::string name) ;

	/*! return plan's name */
	std::string getName();
	/*! execute action on top, if the action is performed successfully, removes it from the plan.
	* If all actions in the plan are achieved, returns true and apply the reward, else, returns false
	*/
	bool usePlan(NPCEntity * e);
	/*! return true if the plan is achieved (i.e. the stack is empty)*/
	bool isPlanAchieved();

	/*! switch the plan for a new one using the name */
	void changePlanTo(std::string planName); 
	
	/*! increase time elapsed */
	void timeElapsedUp() ;

	/*! return time elapsed */
	float getTimeElapsed() ;

	/*! sets a new value for the elapsed time */
	void setElapsedTime(float f);

	/*! checks conditions for cancelling the plan */
	bool planCancel() ;

};


#endif


